package com.wangy.sct.gateway.filter;

import com.alibaba.fastjson.JSON;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;
import java.util.Map;

/**
 * ClassName: DealResponseFilter <br/>
 * Description: 移除InvokeResult的retDataClass，不展现给前端 <br/>
 *
 * @author wangyue
 * @version V1.0.0
 * @date 2018/11/27 12:21 PM
 */
@Configuration
public class DealResponseFilter implements GlobalFilter, Ordered {
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		System.out.println("DealResponseFilter移除InvokeResult的retDataClass");
		ServerHttpResponse originalResponse = exchange.getResponse();
		DataBufferFactory bufferFactory = originalResponse.bufferFactory();
		ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
			@Override
			public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
				if (body instanceof Flux) {
					Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
					return super.writeWith(fluxBody.map(dataBuffer -> {
						// probably should reuse buffers
						byte[] contentByte = new byte[dataBuffer.readableByteCount()];
						dataBuffer.read(contentByte);
						// 释放掉内存
						DataBufferUtils.release(dataBuffer);
						String content = new String(contentByte, Charset.forName("UTF-8"));
						// 移除的retDataClass
						Map map = JSON.parseObject(content, Map.class);
						map.remove("retDataClass");
						return bufferFactory.wrap(JSON.toJSONString(map).getBytes());
					}));
				}
				return super.writeWith(body);
			}
		};
		return chain.filter(exchange.mutate().response(decoratedResponse).build());
	}

	@Override
	public int getOrder() {
		// -1 is response write filter, must be called before that
		return - 2;
	}
}
